#include "VoicePlayer.h"

VoicePlayer::VoicePlayer() : index(1)
{
    this->start();
    this->moveToThread(this);
    QTimer::singleShot(0, this, SLOT(onInit()));
}

VoicePlayer::~VoicePlayer()
{
    qDebug() << __FUNCTION__;
    QTimer::singleShot(0, this, SLOT(onExitThread()));
    this->wait(3000);
}

void VoicePlayer::playBuffer(const QByteArray &data)
{
    QMetaObject::invokeMethod(this, "onPlay", Qt::QueuedConnection, Q_ARG(QByteArray, data));
}

void VoicePlayer::onInit()
{
    qDebug() << __FUNCTION__;
    QAudioFormat format;
    format.setSampleRate(16000);
    format.setChannelCount(1);
    format.setSampleSize(16);
    format.setCodec("audio/pcm");
    format.setByteOrder(QAudioFormat::LittleEndian);
    format.setSampleType(QAudioFormat::UnSignedInt);

    AudioItem item;

    item.audio = new QAudioOutput(format, this);
    item.cache = new QByteArray();
    item.buffer = new QBuffer(item.cache);
    audios_.append(item);

    item.audio = new QAudioOutput(format, this);
    item.cache = new QByteArray();
    item.buffer = new QBuffer(item.cache);
    audios_.append(item);


    QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
    foreach (QAudioDeviceInfo info, devices) {
        qDebug() << info.deviceName();
    }

    QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
    if (!info.isFormatSupported(format)) {
        qWarning() << "cannot play.";
        return;
    }
}

void VoicePlayer::onExitThread()
{
    qDebug() << __FUNCTION__;
    for (auto itr = audios_.begin(); itr != audios_.end(); ++itr) {
        AudioItem &item = *itr;
        item.audio->stop();
        item.audio->deleteLater();
    }

    this->exit();
}

void VoicePlayer::onPlay(QByteArray data)
{
    qDebug() << "on voice player play.";
    if (data.isEmpty()) {
        emit doPlayDone();
        return;
    }

    auto waitForPlay = [&](const AudioItem &item){
        do {
            qApp->processEvents();
            this->msleep(5);
            if (item.buffer->pos() >= item.buffer->size()) {
                break;
            }
        } while(item.audio->state() != QAudio::IdleState);

        emit doPlayDone();
    };
    auto waitForIdle = [&](const AudioItem &item) {
        do {
            qApp->processEvents();
            this->msleep(1);
        } while(item.audio->state() != QAudio::IdleState && item.audio->state() != QAudio::StoppedState);
    };
    auto playCache = [&](const AudioItem &item) {
        item.cache->clear();
        item.cache->append(data);
        item.buffer->close();
        item.buffer->open(QIODevice::ReadOnly);
        item.audio->start(item.buffer);
    };

    if (index == 0) {
        const AudioItem &item = audios_.at(1);
        waitForIdle(item);

        playCache(item);

        waitForPlay(item);
        index = 1;
    } else {
        const AudioItem &item = audios_.at(0);
        waitForIdle(item);

        playCache(item);

        waitForPlay(item);
        index = 0;
    }
}









